/**
 * @brief: 节点参数存储和配置处理文件
 */

#include <string.h>
     
#include "params_config.h"
#include "mcu_uid.h"
#include "cJSON.h"


node_info_t node_info_s[NODE_MAX_CNT];  /* 采集器节点的具体信息 */
gw_info_t gw_info_s = {0, 0};
uint8_t curr_max_node_addr = 0;         /* 当前分配的节点短地址的最大值 */



void parse_node_info(const char *data, uint32_t size)
{
    char recv_msg[512] = {0};
    int i, j, empty_index = 0;
    
    memcpy(recv_msg, &data[7], size);
    
    for(i=0; i<NODE_MAX_CNT; ++i)
        node_info_s[i].traverse_flag = 0;
    
    /* 获取网关的信息 */
    cJSON *root = cJSON_Parse(recv_msg);
    cJSON *gw_addr = cJSON_GetObjectItem(root, "gw_addr");
    cJSON *gw_id = cJSON_GetObjectItem(root, "gw_id");
    cJSON *gw_pub_cycle = cJSON_GetObjectItem(root, "gw_pub_cycle");
    
    gw_info_s.net_addr = gw_addr->valueint;             // 更新网关的信息
    gw_info_s.pub_cycle_min = gw_pub_cycle->valueint;   // 更新网关的信息
    
    /* 获取采集器的信息 */
    cJSON *cjq_num = cJSON_GetObjectItem(root, "cjq_num");
    cJSON *cjq_info_arr = cJSON_GetObjectItem(root, "cjq_info");    // 获取数组
    int cjq_info_arr_size = cJSON_GetArraySize(cjq_info_arr);       // 获取数组中元素的个数
    
    cJSON *item, *dev_type, *cjq_id;
    
    for(i=0; i<cjq_info_arr_size; ++i)
    {
        empty_index = 0;
        item = cJSON_GetArrayItem(cjq_info_arr, i);      // 获取数组中的具体项
        dev_type = cJSON_GetObjectItem(item, "dev_type");
        cjq_id = cJSON_GetObjectItem(item, "cjq_id");
        
        for(j=0; j<NODE_MAX_CNT; ++j)
        {
            if( node_info_s[j].node_addr == 0xFF || node_info_s[j].node_addr == 0x00 ) {
                if(empty_index <= j) // 该位置是空的，记录下第一个空的位置的下标
                    empty_index = j;
                
                continue;
            }
            
            if( strncmp((char *)node_info_s[j].serial_num, cjq_id->valuestring, DEV_SERIAL_NUM_LEN) == 0 ) {  // 与现有的节点序列号一致
                node_info_s[j].traverse_flag = 1;
                break;
            }
        }
        
        if(j == NODE_MAX_CNT) {   // 找遍一圈仍然没有一样的
            memcpy(node_info_s[j].serial_num, cjq_id->valuestring, DEV_SERIAL_NUM_LEN);
            node_info_s[j].dev_type = dev_type->valueint;
            node_info_s[j].join_net_flag = 0;
            node_info_s[j].quit_net_flag = 0;
            node_info_s[j].traverse_flag = 1;
            node_info_s[j].node_addr = curr_max_node_addr + 1;
            curr_max_node_addr++;
        }
    }
    
    for(i=0; i<NODE_MAX_CNT; ++i)
    {
        if( node_info_s[i].node_addr == 0xFF || node_info_s[i].node_addr == 0x00 ) {
                continue;
        }
        
        if( node_info_s[i].traverse_flag == 0 ) // 节点短地址有效，但是新下发的设备信息中无该节点表示需要退网
            node_info_s[i].quit_net_flag = 1;
    }
    
    /* 释放空间 */
    if(root != NULL) {
        cJSON_Delete(root);
        root = NULL; gw_addr = NULL; gw_id = NULL; gw_pub_cycle = NULL; item = NULL; dev_type = NULL; cjq_id = NULL;
    }
}

/**
 * @brief : 从存储器中读取节点参数信息
 * @param : 无
 * @retval: 无
 */
void read_node_info(void)
{
    int i, start_index;
    uint8_t read_buff[NODE_MAX_CNT * NODE_PARAMS_LEN] = {0};    // 20*32
    
    memset(node_info_s, 0xFF, sizeof(node_info_t)*NODE_MAX_CNT);    // 把结构体数组清为0xFF
    
    //eeprom_read_bytes(NODE_PARAMS_START_ADDR, read_buff, sizeof(read_buff)/sizeof(read_buff[0])); // 读取存储的节点信息
    
    for(i=0; i<NODE_MAX_CNT; ++i)
    {
        start_index = NODE_PARAMS_LEN*i;
    
        memcpy(node_info_s[i].serial_num, &(read_buff[start_index]), DEV_SERIAL_NUM_LEN);
        node_info_s[i].node_addr = read_buff[start_index+DEV_SERIAL_NUM_LEN];         
        node_info_s[i].join_net_flag = read_buff[start_index+DEV_SERIAL_NUM_LEN+1];   
        node_info_s[i].quit_net_flag = read_buff[start_index+DEV_SERIAL_NUM_LEN+2];   
        node_info_s[i].dev_type = read_buff[start_index+DEV_SERIAL_NUM_LEN+3]; 
        
        if(node_info_s[i].node_addr != 0xFF && node_info_s[i].node_addr > curr_max_node_addr)
        {
            curr_max_node_addr = node_info_s[i].node_addr;  // 找出当前分配的节点短地址的最大值
        }
    }
}


/**
 * @brief : 保存节点参数信息到存储器中
 * @param : 无
 * @retval: 无
 */
void save_node_info(void)
{
    int i, start_index;
    uint8_t write_buff[NODE_MAX_CNT * NODE_PARAMS_LEN] = {0};   // 20*16
      
    for(i=0; i<NODE_MAX_CNT; ++i)
    {
        start_index = NODE_PARAMS_LEN*i;
        
        memcpy(&(write_buff[start_index]), node_info_s[i].serial_num, DEV_SERIAL_NUM_LEN);  // 16个字节
        write_buff[start_index+DEV_SERIAL_NUM_LEN]   = node_info_s[i].node_addr;       
        write_buff[start_index+DEV_SERIAL_NUM_LEN+1] = node_info_s[i].join_net_flag;   
        write_buff[start_index+DEV_SERIAL_NUM_LEN+2] = node_info_s[i].quit_net_flag;   
        write_buff[start_index+DEV_SERIAL_NUM_LEN+3] = node_info_s[i].dev_type;        
    }
    
    // 将节点信息写入到存储器中
    //eeprom_write_bytes(NODE_PARAMS_START_ADDR, write_buff, sizeof(write_buff)/sizeof(write_buff[0]));
}


/**
 * @brief : 保存节点参数信息到存储器中
 * @param : 无
 * @retval: 无
 */    
void save_gw_info(void)
{     
    uint8_t write_buff[2] = {0};  

    write_buff[0] = gw_info_s.net_addr;
    write_buff[1] = gw_info_s.pub_cycle_min;
    
    // 将节点信息写入到存储器中
    //eeprom_write_bytes(GW_PAARAMS_START_ADDR, write_buff, sizeof(write_buff)/sizeof(write_buff[0]));
}


/**
 * @brief : 从存储器中读取节点参数信息
 * @param : 无
 * @retval: 无
 */
void read_gw_info(void)
{
    uint8_t read_buff[2] = {0};  
      
    //eeprom_read_bytes(GW_PAARAMS_START_ADDR, read_buff, sizeof(read_buff)/sizeof(read_buff[0])); // 读取存储的节点信息
    gw_info_s.net_addr = read_buff[0];
    gw_info_s.pub_cycle_min = read_buff[1];
}


/**
 * @brief : 节点信息测试
 * @param : 无
 * @retval: 无
 */
void node_info_test(void)
{
    node_info_s[0].node_addr = 0x01;
    node_info_s[0].dev_type = DEV_TYPE_CJQ;
    node_info_s[0].join_net_flag = 0x00;
    node_info_s[0].quit_net_flag = 0x00;
    memcpy(node_info_s[0].serial_num, "1234567890ABCDEF", DEV_SERIAL_NUM_LEN);
    
    node_info_s[0].node_addr = 0x02;
    node_info_s[0].dev_type = DEV_TYPE_CJQ;
    node_info_s[0].join_net_flag = 0x00;
    node_info_s[0].quit_net_flag = 0x00;
    memcpy(node_info_s[0].serial_num, "1234567890ABCDEF", DEV_SERIAL_NUM_LEN);
    
    node_info_s[0].node_addr = 0x03;
    node_info_s[0].dev_type = DEV_TYPE_CJQ;
    node_info_s[0].join_net_flag = 0x00;
    node_info_s[0].quit_net_flag = 0x00;
    memcpy(node_info_s[0].serial_num, "1234567890ABCDEF", DEV_SERIAL_NUM_LEN);
}


